<!doctype html>
<html>
<head>
<meta charset='UTF-8'><meta name='viewport' content='width=device-width initial-scale=1'>
<title>README</title></head>
<body><h2>移动端相关</h2>
<h3>1. 移动端1px边框问题的解决方案 (华润集团)</h3>
<ol start='' >
<li>使用小数写px值 通过媒体查询判断设备的像素比 DRP 根据不同像素比写不同的边框大小</li>

</ol>
<pre><code class='language-css' lang='css'>.border { border: 1px solid #ccc }
@media screen and (-webkit-min-device-pixel-ratio: 2) {
    .border { border: 0.5px solid #ccc }
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
    .border { border: 0.333333px solid #ccc }
}

</code></pre>
<ol start='2' >
<li>使用边框图片</li>

</ol>
<p>这样的1张6X6的图片, 9宫格等分填充border-image, 这样元素的4个边框宽度都只有1px</p>
<pre><code class='language-css' lang='css'>@media screen and (-webkit-min-device-pixel-ratio: 2){ 
    .border{ 
        border: 1px solid transparent;
        border-image: url(border.gif) 2 repeat;
    }
}

</code></pre>
<ol start='3' >
<li>使用CSS3 box-shadow</li>

</ol>
<pre><code class='language-css' lang='css'>.shadow {
    -webkit-box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);
    box-shadow:0 1px 1px -1px rgba(255, 0, 0, 0.5);
}
</code></pre>
<ol start='4' >
<li>viewport结合rem (推荐使用)</li>

</ol>
<pre><code class='language-html' lang='html'>//devicePixelRatio=2设置meta
&lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no&quot;&gt;

//devicePixelRatio=3设置meta
&lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no&quot;&gt;
</code></pre>
<ol start='5' >
<li>使用 :before     ,   :after 与  transform（推荐使用）</li>

</ol>
<pre><code class='language-css' lang='css'>//第一种方法
//构建1个伪元素, 将它的长宽放大到2倍, 边框宽度设置为1px, 再以transform缩放到50%
.radius-border{
    position: relative;
}
@media screen and (-webkit-min-device-pixel-ratio: 2){
    .radius-border:before{
        content: &quot;&quot;;
        pointer-events: none; /* 防止点击触发 */
        box-sizing: border-box;
        position: absolute;
        width: 200%;
        height: 200%;
        left: 0;
        top: 0;
        border-radius: 8px;
        border:1px solid #999;
        -webkit-transform(scale(0.5));
        -webkit-transform-origin: 0 0;
        transform(scale(0.5));
        transform-origin: 0 0;
    }
}

@media screen and (-webkit-min-device-pixel-ratio: 3) {
    .radius-border:before{
        content: &quot;&quot;;
        pointer-events: none; /* 防止点击触发 */
        box-sizing: border-box;
        position: absolute;
        width: 200%;
        height: 200%;
        left: 0;
        top: 0;
        border-radius: 8px;
        border:1px solid #999;
        -webkit-transform(scale(0.3333));
        -webkit-transform-origin: 0 0;
        transform(scale(0.3333));
        transform-origin: 0 0;
    }
}
</code></pre>
<h3>2. 移动屏幕适配方案 (华润集团)</h3>
<ol start='' >
<li>使用rem+媒体查询实现</li>
<li>使用rem+js实现</li>
<li>使用rem+vw实现</li>

</ol>
<p>rem是什么是一个相对单位参照根元素的字体大小 只要动态修改跟元素字体大小所有rem单位都会跟着改变
那么rem的根元素改变参照点是谁： 设计图 以设计图大小对应的的屏幕作为参照点  假设一个设计图大小对应的真实屏幕的根元素值 
例如750设计图真实屏幕是375 根元素100px 计算其他屏幕就使用 其他屏幕大小/375 * 100 求到其他屏幕的根元素大小</p>
<h2>CSS相关</h2>
<h3>3. css3中box-shadow存在的问题 (华润集团)</h3>
<ol start='' >
<li><p>css3中box-shadow的溢出问题
子容器加了box-shadow在父容器中可能存在溢出 可以通过给父元素添加overflow:hidden解决</p>
</li>
<li><p>box-shadow阴影被覆盖问题</p>
<ol start='' >
<li>使用相对定位解决position:relative和z-index提高层数可以把阴影显示出来</li>
<li>开启gpu加速, 设置3d效果 { transform: translate3d(0, 0, 0); } </li>

</ol>
</li>

</ol>
<h2>JS相关</h2>
<h3>1. 数组转成字符串的方式 (智理软件)</h3>
<ol start='' >
<li>使用toString方法 转成字符串</li>

</ol>
<p>例如 var arr = [1,2,3]</p>
<p>arr.toString() ==  &#39;1,2,3&#39;;</p>
<ol start='2' >
<li>使用join()方法 转成字符串</li>

</ol>
<p>例如 var arr = [1,2,3]</p>
<p>arr.join(&#39;,&#39;) ==  &#39;1,2,3&#39;;
还可以自由控制需要什么隔开例如 - , 如果不需要什么隔开就写空
arr.join(&#39;&#39;) ==  &#39;123&#39;;</p>
<h3>2. JS数组的排序方式(智理软件)</h3>
<ol start='' >
<li>使用数组的sort函数可以实现排序</li>

</ol>
<p>但是默认sort是按照ASCII编码排序的
如果需要按照数值的从小到大 从大到小需要使用第二个参数 是一个回调函数 回调函数需要两个参数 用来说明你要按照什么方式排序</p>
<p>例如a,b<br/>
如果 a - b &lt; 0 表示 a 比 b小 那么真实的a代表的数字就会排在b前面  <br/>
如果 a - b == 0 那么表示2个值相等 就按顺序排序
如果 a - b &gt; 0 表示 a比b大 那么真实a代表的数组就会排在b后面</p>
<pre><code class='language-js' lang='js'>
function sortNumber(a, b) {
           
    return a - b  // 从小到大
    // return b - a  // 从大到小
}

var arr = [10, 5, 40, 25, 1000, 1]

document.write(arr + &quot;&lt;br /&gt;&quot;)
document.write(arr.sort(sortNumber));// 1 5 10 25 40 1000 从小到大
</code></pre>
<ol start='2' >
<li>自己使用算法实现排序 例如 冒泡排序</li>

</ol>
<pre><code class='language-js' lang='js'>var arr = [10, 20, 1, 2];
var t;
for(var i=0;i&lt;arr.length;i++){
    for(j=i+1;j&lt;arr.length;j++){
        if(arr[i]&gt;arr[j]){
            t=arr[i];
            arr[i]=arr[j];
            arr[j]=t;
        }
    }
}
console.log(arr);  //[1, 2, 10, 20]
</code></pre>
<ol start='3' >
<li>快速排序</li>

</ol>
<pre><code class='language-js' lang='js'>// 快速排序
var quickSort = function(arr) {
    if(arr.length &lt; 1) {//如果数组就是一项，那么可以直接返回
        return arr;
    }
    var centerIndex = Math.floor(arr.length / 2);//获取数组中间的索引
    var centerValue = arr[centerIndex];//获取数组中间项
    var left = [], right = [];
    for(var i = 0; i &lt; arr.lenght; i++){
        if(arr[i] &lt; centerValue){
            left.push(arr[i]);
        }else{
            right.push(arr[i]);
        }
    }
    return quickSort(left).contanct([centerValue], quickSort(right));//递归调用
}
</code></pre>
<h3>3. JSON转换(智理软件)</h3>
<ol start='' >
<li>将JS对象转成JSON字符串
var str = JSON.stringify(obj);</li>
<li>将JSON字符串转成JS对象</li>

</ol>
<p>var obj = JSON.parse(str); </p>
<h3>4. 对原型链的理解(华润集团)</h3>
<ol start='' >
<li><p>什么是原型链
简单来说就是对象和构造函数之间连接的一个链条 简称原型链</p>
</li>
<li><p>原型链的作用
可以通过原型链继承构造函数对象定义的一些公共的属性方法</p>
</li>
<li><p>原型链的流程图</p>
<p><img src='./JS相关/原型链流程图.png' alt='原型链流程图' referrerPolicy='no-referrer' /></p>
</li>

</ol>
<h3>5. JS变量提升和自执行函数的面试题</h3>
<pre><code class='language-js' lang='js'>(function(){
    console.log(a);// undefined 虽然此时在函数内打印有a 因为var变量声明会提前所以不会报错 但是赋值不会提前所以a没有值是 undefined
    var a = b = 1;        
})();        
console.log(b);//1 因为 var a = b = 1 其实b并没在里面var所以 b是全局变量并且赋值为了1所以是1
console.log(a);// 因为 var a = b = 1; 这个var是在自执行函数里面的自执行函数是一个函数作用域 所以var a是函数内的局部变量所以外界拿不到 即是报错  a is not defined
</code></pre>
<h3>6. JS this指向的面试题</h3>
<pre><code class='language-js' lang='js'>
var name = &#39;王五&#39;;
var obj = {
    name: &#39;张三&#39;,
    getName:function(){
        return this.name;
    },
    children:{
        name:&#39;李四&#39;,
        getName:function(){
            return this.name;
        }
    }
}    
console.log(obj.getName());//张三
console.log(obj.children.getName());//李四
var getName = obj.children.getName;
console.log(getName());//王五
// 那么如果我想调用getName() 但是想打印张三怎么办 可以使用call函数改变调用当前函数的this指针
console.log(getName.call(obj));//张三
</code></pre>
<h3>7. 使用JS的类实现一个栈的类 并实现栈里面的常用API</h3>
<pre><code class='language-js' lang='js'>// 定义一个栈的类 实现栈的push pop getMax getMin等函数 
// 并实现先进后出 后进先出 而且能够不断求出 当前栈里面的数据的最大值最小值
class Stack {
    constructor(){
        this.dataStack = [];
        this.maxStack = [];
        this.minStack = [];

    }
    // 入栈
    push(item){
        if(this.minStack.length &lt;= 0){
            this.minStack.push(item)
        }
        else if(item &lt;= this.getMin()){
            this.minStack.push(item)
        }

        if(this.maxStack.length &lt;= 0){
            this.maxStack.push(item)
        }
        else if(item &gt;= this.getMax()){
            this.maxStack.push(item)
        }
        this.dataStack.push(item);                
    }
    // 出栈
    pop(){
        if(this.dataStack.length &lt;= 0){
            return 
        }
        let value = this.dataStack.pop();
        
        if(value == this.getMin()){
            this.minStack.pop()
        }
        if(value == this.getMax()){
            this.maxStack.pop();
        }
        return value;
    }
    // 求最小值
    getMin(){               
        if(this.minStack.length &lt;=0){
            return 0;
        }
        return this.minStack[this.minStack.length-1];
    }
    // 求最大值
    getMax(){             
        if(this.maxStack.length &lt;=0){
            return 0;
        }                
        return this.maxStack[this.maxStack.length-1];
    }
}    
// 创建栈的对象
var stack = new Stack();
// 调用入栈
stack.push(3);
stack.push(5);
stack.push(10);
stack.push(7);
stack.push(6);
// 调用求最大值 最小值的函数
console.log(stack.dataStack);       
console.log(stack.getMax());
console.log(stack.getMin());
// 出栈
stack.pop();
stack.pop();
// 出栈后的最大值最小值
console.log(stack.getMax());
console.log(stack.getMin());
console.log(stack.minStack);
console.log(stack.maxStack);
stack.pop();
console.log(stack.getMax());
console.log(stack.getMin());
console.log(stack.minStack);
console.log(stack.maxStack);
stack.pop();
console.log(stack.getMax());
console.log(stack.getMin());
console.log(stack.dataStack);
console.log(stack.maxStack);
stack.pop();
console.log(stack.getMax());
console.log(stack.getMin());
console.log(stack.dataStack);
console.log(stack.maxStack);
</code></pre>
<h2>存储相关</h2>
<h3>cookies sessionStorage和localstorage区别(华润集团)</h3>
<p>相同点：都存储在客户端
不同点：1.存储大小</p>
<p>· cookie数据大小不能超过4k。</p>
<p>· sessionStorage和localStorage 虽然也有存储大小的限制，但比cookie大得多，可以达到5M或更大。</p>
<p>2.有效时间</p>
<p>· localStorage    存储持久数据，浏览器关闭后数据不丢失除非主动删除数据；</p>
<p>· sessionStorage  数据在当前浏览器窗口关闭后自动删除。</p>
<p>· cookie          设置的cookie过期时间之前一直有效，即使窗口或浏览器关闭</p>
<ol start='3' >
<li>数据与服务器之间的交互方式</li>

</ol>
<p>· cookie的数据会自动的传递到服务器，服务器端也可以写cookie到客户端</p>
<p>· sessionStorage和localStorage不会自动把数据发给服务器，仅在本地保存。</p>
<h2>vue相关</h2>
<h3>1. react和vue有哪些不同，说说你对这两个框架的看法 (华润集团)</h3>
<p>相同点</p>
<p>· 都支持服务器端渲染</p>
<p>· 都有Virtual DOM,组件化开发,通过props参数进行父子组件数据的传递,都实现webComponent规范</p>
<p>· 数据驱动视图</p>
<p>· 都有支持native的方案,React的React native,Vue的weex</p>
<p>不同点</p>
<p>· React严格上只针对MVC的view层,Vue则是MVVM模式</p>
<p>· virtual DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树.而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制</p>
<p>· 组件写法不一样, React推荐的做法是 JSX + inline style, 也就是把HTML和CSS全都写进JavaScript了,即&#39;all in js&#39;; Vue推荐的做法是webpack+vue-loader的单文件组件格式,即html,css,js写在同一个文件但是会区分开标签;</p>
<p>· 数据绑定: vue实现了数据的双向绑定,react数据流动是单向的</p>
<p>· state对象在react应用中不可变的,需要使用setState方法更新状态;在vue中,state对象不是必须的,数据由data属性在vue对象中管理</p>
<h3>2. vue的双向绑定原理 (华润集团)</h3>
<ol start='' >
<li>Vue.js 采用的是 数据劫持+发布/订阅模式 的方式，通过 Object.defineProperty() 来劫持各个属性的 setter/getter， 在数据变动时发布消息给订阅者（Wacther）, 触发相应的监听回调</li>
<li>简单实现</li>

</ol>
<pre><code class='language-html' lang='html'>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
    &lt;head&gt;
        &lt;title&gt;双向绑定最最最初级demo&lt;/title&gt;
        &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div id=&quot;app&quot;&gt;
            &lt;input type=&quot;text&quot; id=&quot;txt&quot;&gt;
            &lt;p id=&quot;show-txt&quot;&gt;&lt;/p&gt;
        &lt;/div&gt;
    &lt;/body&gt;
    &lt;script&gt;
        var obj={}
        Object.defineProperty(obj,&#39;txt&#39;,{
            get:function(){
                return obj
            },
            set:function(newValue){
                document.getElementById(&#39;txt&#39;).value = newValue
                document.getElementById(&#39;show-txt&#39;).innerHTML = newValue
            }
        })
        document.addEventListener(&#39;keyup&#39;,function(e){
            obj.txt = e.target.value
        })
    &lt;/script&gt;
&lt;/html&gt;
</code></pre>
<h3>2. vue的生命周期 （华润集团 炫酷网络）</h3>
<ol start='' >
<li>什么是vue的声明周期
Vue 实例从创建到销毁的过程，就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程，我们称这是 Vue 的生命周期。  <br/></li>
<li>组件第一次加载会触发哪些声明周期函数
第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子</li>
<li>DOM 渲染在 哪个周期中就已经完成
DOM 渲染在 mounted 中就已经完成了。</li>
<li>声明周期各个函数的作用
生命周期钩子的一些使用方法： beforecreate : 可以在这加个loading事件，在加载实例时触发 created : 初始化完成时的事件写在这里，如在这结束loading事件，异步请求也适宜在这里调用 mounted : 挂载元素，获取到DOM节点 updated : 如果对数据统一处理，在这里写上相应函数 beforeDestroy : 可以做一个确认停止事件的确认框 nextTick : 更新数据后立即操作dom</li>
<li>当keep组件激活时会调用哪个生命周期的函数
activated 该钩子在服务器端渲染期间不被调用。</li>
<li>当keep-alive组件停用时调用。 
deactivated 该钩子在服务端渲染期间不被调用。 </li>
<li>keep的调用时机 （炫酷网络）</li>

</ol>
<p>activated调用时机：</p>
<p>第一次进入缓存路由/组件，在mounted后面，beforeRouteEnter守卫传给 next 的回调函数之前调用：</p>
<pre><code>beforeMount=&gt; 如果你是从别的路由/组件进来(组件销毁destroyed/或离开缓存deactivated)=&gt;
mounted=&gt; activated 进入缓存组件 =&gt; 执行 beforeRouteEnter回调

因为组件被缓存了，再次进入缓存路由/组件时，不会触发这些钩子：

// beforeCreate created beforeMount mounted 都不会触发。
所以之后的调用时机是：

组件销毁destroyed/或离开缓存deactivated =&gt; activated 进入当前缓存组件 
=&gt; 执行 beforeRouteEnter回调
// 组件缓存或销毁，嵌套组件的销毁和缓存也在这里触发
</code></pre>
<ol start='8' >
<li>组件缓存和不缓存调用的生命周期</li>

</ol>
<p>（1）不缓存： 
进入的时候可以用created和mounted钩子，离开的时候用beforeDestory和destroyed钩子,beforeDestory可以访问this，destroyed不可以访问this。</p>
<p>（2）缓存了组件： 
缓存了组件之后，再次进入组件不会触发beforeCreate、created 、beforeMount、 mounted，如果你想每次进入组件都做一些事情的话，你可以放在activated进入缓存组件的钩子中。 
同理：离开缓存组件的时候，beforeDestroy和destroyed并不会触发，可以使用deactivated离开缓存组件的钩子来代替</p>
<ol start='9' >
<li><p>完整的触发顺序</p>
<pre><code> 触发钩子的完整顺序：

 将路由导航、keep-alive、和组件生命周期钩子结合起来的，触发顺序，假设是从a组件离开，第一次进入b组件：

 1. beforeRouteLeave:路由组件的组件离开路由前钩子，可取消路由离开。

 2. beforeEach: 路由全局前置守卫，可用于登录验证、全局路由loading等。

 3. beforeEnter: 路由独享守卫

 4. beforeRouteEnter: 路由组件的组件进入路由前钩子。

 5. beforeResolve:路由全局解析守卫

 6. afterEach:路由全局后置钩子

 7. beforeCreate:组件生命周期，不能访问this。

 8. created:组件生命周期，可以访问this，不能访问dom。

 9. beforeMount:组件生命周期

 10. deactivated: 离开缓存组件a，或者触发a的beforeDestroy和destroyed组件销毁钩子。

 11. mounted:访问/操作dom。

 12. activated:进入缓存组件，进入a的嵌套子组件(如果有的话)。

 13. 执行beforeRouteEnter回调函数next。
</code></pre>
</li>

</ol>
<h3>3. vue的computed属性 (华润集团)</h3>
<ol start='' >
<li>computed用来监控自己定义的变量，该变量不在data里面声明，直接在computed里面定义，然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理</li>
<li>computed比较适合对多个变量或者对象进行处理后返回一个结果值，也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化，举例：购物车里面的商品列表和总金额之间的关系，只要商品列表里面的商品数量发生变化，或减少或增多或删除商品，总金额都应该发生变化。这里的这个总金额使用computed属性来进行计算是最好的选择</li>
<li>computed和watch的区别
watch主要用于监控vue实例的变化，它监控的变量当然必须在data里面声明才可以，它可以监控一个变量，也可以是一个对象</li>

</ol>
<pre><code class='language-js' lang='js'>　data(){
　　　return {
　　　　　　　　　　example0:&quot;&quot;,
　　　　　　　　　　example1:&quot;&quot;,
　　　　　　　　　　example2:{
　　　　　　　　　　　　inner0:1, 　　　　　　　　　
                　　　innner1:2 　　　　　　　　　
            　}
　　　　　　}
　　　　},
watch:{
　example0(newVal,oldVal){//监控单个变量
           ……
   }，
example2(newVal,oldVal){//监控对象
           ……
   }，
}
</code></pre>
<p>watch一般用于监控路由、input输入框的值特殊处理等等，它比较适合的场景是一个数据影响多个数据</p>
<p>计算属性可用于快速计算视图（View）中显示的属性。这些计算将被缓存，并且只在需要时更新</p>
<h3>4. vuex (所有公司)</h3>
<ol start='' >
<li><p>什么时候需要使用vuex : 当项目业务复杂 页面之间很多关联数据需要交互的时候</p>
</li>
<li><p>本地存储和vuex的区别</p>
<ol start='' >
<li>vuex是状态管理，是为了解决跨组件之间数据共享问题的，一个组件的数据变化会映射到使用这个数据的其他组件当中。如果刷新页面，之前存储的vuex数据全部都会被初始化掉</li>
<li>localStorage是H5提供的一个更简单的数据存储方式，之前是用cookie存放数据，但是cookie的数据量太小，所以就用localStorage，它可以有5M的限制，不受刷新页面的控制，长久保存</li>
<li>所以，在用vue进行项目开发的时候，什么时候用到vuex呢？</li>

</ol>
<p>当应用遇到多个组件共享状态时候，即：多个视图依赖于同一个状态，不同视图的行为需要变更同一状态。</p>
<p>vuex的官网也说了，对于页面之间的传参对于多层嵌套组件将会很繁琐，而且对于兄弟组件之间的状态传递无能为力。所以就将这些组件的共享状态抽取出来，以一个全局单例模式管理，即vuex</p>
<pre><code>1.【响应式】vuex的状态存储是响应式的，当Vue组件从store中读取状态的时候，若store中的状态发生变化，那么相应的组件也会得到高效更新。

2.【不能直接改变store】不能直接改变store的变化，改变store中状态的唯一途径是commit mutation。方便于跟踪每一个状态的变化
</code></pre>
<ol start='4' >
<li>但是localstorage改变了不会自动动态更新视图需要手动获取更新</li>

</ol>
</li>

</ol>
<h3>5. vuex中常见的属性 (所有公司)</h3>
<ol start='' >
<li><p>vuex有哪几种属性
有五种，分别是 State、 Getter、Mutation 、Action、 Module</p>
</li>
<li><p>vuex的State特性是？</p>
<ol start='' >
<li>Vuex就是一个仓库，仓库里面放了很多对象。其中state就是数据源存放地，对应于与一般Vue对象里面的data</li>
<li>state里面存放的数据是响应式的，Vue组件从store中读取数据，若是store中的数据发生改变，依赖这个数据的组件也会发生更新</li>
<li>它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中</li>

</ol>
</li>
<li><p>vuex的Getter特性是？</p>
<ol start='' >
<li>getters 可以对State进行计算操作，它就是Store的计算属性</li>
<li>虽然在组件内也可以做计算属性，但是getters 可以在多组件之间复用</li>
<li>如果一个状态只在一个组件内使用，是可以不用getters</li>

</ol>
</li>
<li><p>vuex的Mutation特性是？</p>
<ol start='' >
<li>Action 类似于 mutation，不同在于：</li>
<li>Action 提交的是 mutation，而不是直接变更状态。</li>
<li>Action 可以包含任意异步操作</li>

</ol>
</li>
<li><p>Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中？</p>
<ol start='' >
<li>如果请求来的数据是不是要被其他组件公用，仅仅在请求的组件内使用，就不需要放入vuex 的state里。</li>
<li>如果被其他地方复用，这个很大几率上是需要的，如果需要，请将请求放入action里，方便复用，并包装成promise返回，在调用处用async await处理返回的数据。如果不要复用这个请求，那么直接写在vue文件里很方便。</li>

</ol>
</li>

</ol>
<h2>ES6相关 (所有公司)</h2>
<h3>1.es6熟悉吗，说几个es6的新增的一些东西</h3>
<ol start='' >
<li>新增声明命令let和const</li>
<li>模板字符串（Template String）</li>
<li>函数的扩展(默认参数和箭头函数)</li>
<li>对象扩展</li>
<li>import和export</li>
<li>Promise</li>
<li>解构赋值</li>
<li>展开运算符(...运算符)</li>

</ol>
<h3>2. let count的详解</h3>
<ol start='' >
<li>let 和 const 都是块级作用域。以{}代码块作为作用域范围 只能在代码块里面使用。</li>
<li>不存在变量提升，只能先声明再使用，否则会报错。在代码块内，在声明变量之前，该变量都是不可用的。这在语法上，称为“暂时性死区”（temporal dead zone，简称 TDZ）。</li>
<li>在同一个代码块内，不允许重复声明。</li>
<li>const声明的是一个只读常量，在声明时就需要赋值。（如果 const 的是一个对象，对象所包含的值是可以被修改的。抽象一点儿说，就是对象所指向的地址不能改变，而变量成员是可以修改的。）</li>

</ol>
<h3>3. 模板字符串详解</h3>
<p>用一对反引号(`)标识，它可以当作普通字符串使用，也可以用来定义多行字符串，也可以在字符串中嵌入变量，js表达式或函数，变量、js表达式或函数需要写在${ }中</p>
<pre><code class='language-js' lang='js'>var str = `abc
def
gh`;
console.log(str);
let name = &quot;小明&quot;;
function a() {
    return &quot;ming&quot;;
}
console.log(`我的名字叫做${name}，年龄${17+2}岁，性别${&#39;男&#39;}，游戏ID：${a()}`);
</code></pre>
<h3>4. 函数的扩展详解</h3>
<ol start='' >
<li>可以给函数参数设置默认值</li>

</ol>
<pre><code class='language-js' lang='js'>function A(a,b=1){
    console.log(a+b);
}
A(1);    //2
A(2+3);  //5
</code></pre>
<ol start='2' >
<li><p>箭头函数</p>
<ol start='' >
<li>可以省略function关键字 </li>
<li>可以不写函数名</li>
<li>如果只有一个表达式可以不需要写{} 和 返回值</li>

</ol>
</li>

</ol>
<pre><code class='language-js' lang='js'>
//省略写法
var people = name =&gt; &#39;hello&#39; + name;
 
var getFullName = (firstName, lastName) =&gt; {
    var fullName = firstName + lastName;
    return fullName;
}

</code></pre>
<h3>5. 对象的扩展详解</h3>
<ol start='' >
<li>属性的简写。ES6 允许在对象之中，直接写变量。这时，属性名为变量名, 属性值为变量的值</li>
<li>方法简写</li>

</ol>
<pre><code class='language-js' lang='js'>
var o = {
  method() {
    return &quot;Hello!&quot;;
  }
};
 
// 等同于
var o = {
  method: function() {
    return &quot;Hello!&quot;;
  }
};
</code></pre>
<ol start='3' >
<li>Object.keys()方法，获取对象的所有属性名或方法名（不包括原形的内容），返回一个数组</li>

</ol>
<pre><code class='language-js' lang='js'>
var obj={name: &quot;john&quot;, age: &quot;21&quot;, getName: function () { alert(this.name)}};
console.log(Object.keys(obj));    // [&quot;name&quot;, &quot;age&quot;, &quot;getName&quot;]
console.log(Object.keys(obj).length);    //3
 
console.log(Object.keys([&quot;aa&quot;, &quot;bb&quot;, &quot;cc&quot;]));    //[&quot;0&quot;, &quot;1&quot;, &quot;2&quot;]
console.log(Object.keys(&quot;abcdef&quot;));    //[&quot;0&quot;, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;]

</code></pre>
<ol start='4' >
<li>Object.assign ()，assign方法将多个原对象的属性和方法都合并到了目标对象上面。可以接收多个参数，第一个参数是目标对象，后面的都是源对象</li>

</ol>
<pre><code class='language-js' lang='js'>
var target  = {}; //目标对象
var source1 = {name : &#39;ming&#39;, age: &#39;19&#39;}; //源对象1
var source2 = {sex : &#39;女&#39;}; //源对象2
var source3 = {sex : &#39;男&#39;}; //源对象3，和source2中的对象有同名属性sex
Object.assign(target,source1,source2,source3);
 
console.log(target);    //{name : &#39;ming&#39;, age: &#39;19&#39;, sex: &#39;男&#39;}
</code></pre>
<h3>6. import和export模块化引包和导出详解</h3>
<ol start='' >
<li>export用于对外输出本模块（一个文件可以理解为一个模块）变量的接口。</li>
<li>import用于在一个模块中加载另一个含有export接口的模块。</li>
<li>import和export命令只能在模块的顶部，不能在代码块之中</li>

</ol>
<pre><code class='language-js' lang='js'>//导入部分
//全部导入
import Person from &#39;./example&#39;
 
//将整个模块所有导出内容当做单一对象，用as起别名
import * as example from &quot;./example.js&quot;
console.log(example.name)
console.log(example.getName())
 
//导入部分
import { name } from &#39;./example&#39;
 
//导出部分
// 导出默认
export default App
 
// 部分导出
export class User extend Component {};
</code></pre>
<h3>7. Promise对象异步对象</h3>
<ol start='' >
<li>Promise的概念和作用： Promise是异步编程的一种解决方案，将异步操作以同步操作的流程表达出来，避免了层层嵌套的回调函数</li>
<li>Promise的状态： 它有三种状态，分别是pending进行中、resolved已完成、rejected已失败</li>
<li>Promise语法： Promise 构造函数包含一个参数和一个带有 resolve（解析）和 reject（拒绝）两个参数的回调。在回调中执行一些操作（例如异步），如果一切都正常，则调用 resolve，否则调用 reject。对于已经实例化过的 promise 对象可以调用 promise.then() 方法，传递 resolve 和 reject 方法作为回调。then()方法接收两个参数：onResolve和onReject，分别代表当前 promise 对象在成功或失败时</li>

</ol>
<p>语法：</p>
<pre><code class='language-js' lang='js'>
var promise = new Promise((resolve, reject) =&gt; {
    var success = true;
    if (success) {
        resolve(&#39;成功&#39;);
    } else {
        reject(&#39;失败&#39;);
    }
}).then(
    (data) =&gt; { console.log(data)},
    (data) =&gt; { console.log(data)}
)
</code></pre>
<p>执行过程：</p>
<pre><code class='language-js' lang='js'>
setTimeout(function() {
    console.log(0);
}, 0);
var promise = new Promise((resolve, reject) =&gt; {
    console.log(1);
    setTimeout(function () {
        var success = true;
        if (success) {
            resolve(&#39;成功&#39;);
        } else {
            reject(&#39;失败&#39;);
        }
    },2000);
}).then(
    (data) =&gt; { console.log(data)},
    (data) =&gt; { console.log(data)}
);
console.log(promise);	//&lt;pending&gt; 进行中
setTimeout(function () {
    console.log(promise);	//&lt;resolved&gt; 已完成
},2500);
console.log(2);
 
//1
//Promise {&lt;pending&gt;}
//2
//0
//成功
//Promise {&lt;resolved&gt;: undefined}
</code></pre>
<h3>8. 解构赋值详解</h3>
<p>ES6 允许按照一定模式，从数组和对象中提取值，对变量进行赋值，这被称为解构（Destructuring）</p>
<ol start='' >
<li><p>数组的解构赋值
数组中的值会自动被解析到对应接收该值的变量中，数组的解构赋值要一一对应 如果有对应不上的就是undefined</p>
<pre><code class='language-js' lang='js'>
var [name, pwd, sex]=[&quot;小周&quot;, &quot;123456&quot;, &quot;男&quot;];
console.log(name) //小周
console.log(pwd)//123456
console.log(sex)//男
</code></pre>
</li>
<li><p>对象的解构赋值
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的，变量的取值由它的位置决定；而对象的属性没有次序，变量必须与属性同名，才能取到正确的值</p>
<pre><code class='language-js' lang='js'>
var obj={name:&quot;小周&quot;, pwd:&quot;123456&quot;, sex:&quot;男&quot;}
var {name, pwd, sex}=obj;
console.log(name) //小周
console.log(pwd)//123456
console.log(sex)//男

//如果想要变量名和属性名不同，要写成这样
let { foo: foz, bar: baz } = { foo: &quot;aaa&quot;, bar: &quot;bbb&quot; };
console.log(foz) // &quot;aaa&quot;
console.log(foo) // error: foo is not defined
</code></pre>
</li>

</ol>
<h3>9. 展开运算符(...运算符)</h3>
<ol start='' >
<li>将字符串转成数组</li>

</ol>
<pre><code class='language-js' lang='js'>var str=&quot;abcd&quot;;
console.log([...str]) // [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;]
</code></pre>
<ol start='2' >
<li>将集合转成数组</li>

</ol>
<pre><code class='language-js' lang='js'>var sets=new Set([1,2,3,4,5])
console.log([...sets]) // [1, 2, 3, 4, 5]
</code></pre>
<ol start='3' >
<li>两个数组的合并</li>

</ol>
<pre><code class='language-js' lang='js'>var a1=[1,2,3];
var a2=[4,5,6];
console.log([...a1,...a2]); //[1, 2, 3, 4, 5, 6]
</code></pre>
<ol start='4' >
<li>在函数中，用来代替arguments参数</li>

</ol>
<pre><code class='language-js' lang='js'>rest参数  …变量名称

rest 参数是一个数组 ，它的后面不能再有参数，不然会报错

function func(...args){
    console.log(args);//[1, 2, 3, 4]
}
func(1, 2, 3, 4);
 
function f(x, ...y) {
    console.log(x);
    console.log(y);
}
f(&#39;a&#39;, &#39;b&#39;, &#39;c&#39;);     //a 和 [&quot;b&quot;,&quot;c&quot;]
f(&#39;a&#39;)                //a 和 []
f()                   //undefined 
</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>
</html>